/**
 * Copyright (c) 2023 murenchao
 * taomu is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *       http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package cool.taomu.toolkit.druid.provider

import com.alibaba.druid.pool.DruidDataSource
import com.google.inject.Provider
import cool.taomu.toolkit.entity.DataSourceConfigEntity
import java.lang.ref.WeakReference
import javax.sql.DataSource
import org.slf4j.LoggerFactory

class DruidDataSourceProvider implements Provider<DataSource> {
    
    val static LOG = LoggerFactory.getLogger(DruidDataSourceProvider)

    DataSourceConfigEntity config
    
    new(DataSourceConfigEntity config){
        this.config = config
    }

    def DruidDataSource toDruidDataSource(DataSourceConfigEntity config) {
        val dataSource = new DruidDataSource()

        // 基础信息
        dataSource.setDriverClassName(config.driverClassName)
        dataSource.setUrl(config.url)
        dataSource.setUsername(config.username)
        dataSource.setPassword(config.password)
        dataSource.defaultAutoCommit = config.defaultAutoCommit !== null ? config.defaultAutoCommit : true

        // 连接池大小相关
        dataSource.setInitialSize(config.initialSize)
        dataSource.setMinIdle(config.minIdle)
        dataSource.setMaxActive(config.maxActive)
        dataSource.setMaxWait(config.maxWait)
        // dataSource.setValidationInterval(config.validationInterval)
        // 连接有效性检测
        dataSource.setTestWhileIdle(config.testWhileIdle ? config.testWhileIdle : true)
        dataSource.setTestOnBorrow(config.testOnBorrow ? config.testOnBorrow : false)
        dataSource.setTestOnReturn(config.testOnReturn ? config.testOnReturn : false)
        // dataSource.setUseValidationQuery(config.useValidationQuery ? config.useValidationQuery : true)
        if (config.validationQuery !== null) {
            dataSource.setValidationQuery(config.validationQuery)
        } else {
            dataSource.setValidationQuery("SELECT 1")
        }

        // Druid 特有配置
        dataSource.setUseUnfairLock(config.useUnfairLockForPooling ? config.useUnfairLockForPooling : true)

        switch config.filters {
            case 1: dataSource.setFilters("stat")
            case 2: dataSource.setFilters("wall")
            case 3: dataSource.setFilters("stat,wall")
            default: dataSource.setFilters("stat")
        }

        dataSource.setResetStatEnable(config.resetStatEnable ? config.resetStatEnable : true)
        dataSource.setLogAbandoned(config.logAbandoned ? config.logAbandoned : true)
        dataSource.setRemoveAbandoned(config.removeAbandoned ? config.removeAbandoned : true)
        dataSource.setRemoveAbandonedTimeout((config.abandonedTimeout / 1000) as int)

        // JMX 支持
        dataSource.setUseGlobalDataSourceStat(config.enableJmx ? config.enableJmx : true)

        // 网络与安全
        if (config.sslEnabled) {
            if (config.sslTrustStorePath !== null) {
                dataSource.addConnectionProperty("javax.net.ssl.trustStore", config.sslTrustStorePath)
            }
            if (config.sslTrustStorePassword !== null) {
                dataSource.addConnectionProperty("javax.net.ssl.trustStorePassword", config.sslTrustStorePassword)
            }
        }

        // 初始化SQL脚本
        if (config.connectionInitSqls !== null && !config.connectionInitSqls.empty) {
            dataSource.setConnectionInitSqls(config.connectionInitSqls)
        }

        // 健康检查
        dataSource.setValidationQueryTimeout((config.healthCheckTimeout / 1000) as int)

        return dataSource
    }

    override get() {
        var dsConfig = this.config
        if(dsConfig === null){
            LOG.info("DataSourceConfigEntity 配置类为 空")
        }
        return toDruidDataSource(this.config);
    }
}
